from Crypto.Util import randpool
from threading import local

def default_config(c):
    c.clutch.db._configure(
        uri='sqlite:///',
        schema=None,
        table_prefix='')
    c.clutch.view._configure(
        default_html_engine='genshi',
        default_text_engine='jinja'
        )
##    c.session._configure(
##         type=repr('cookie'),
##        key=repr('appointment'),
##        secret=repr(RandomPool.get_string(40)),
##        validate_key=repr(RandomPool.get_string(10)),
##        timeout=repr(120))

class ConfigObj(dict):

    def __init__(self, root=True):
        if root:
            default_config(self)

    def __getattr__(self, name):
        if name in self:
            return self[name]
        self[name] = result = ConfigObj(False)
        return result

    def __setattr__(self, name, value):
        if name.startswith('_'):
            self.__dict__[name] = value
        else:
            self[name] = value

    def _traverse(self, parts):
        if not parts: return self
        return getattr(self, parts[0])._traverse(parts[1:])

    def _configure(self, **dct):
        for k, v in dct.items():
            parts = k.split('.')
            if len(parts) == 1:
                setattr(self, k, v)
            else:
                cp = self._traverse(parts[:-1])
                setattr(cp, parts[-1], v)

    def _flatten(self):
        for k,v in self.items():
            if isinstance(v, ConfigObj):
                for line in v._flatten():
                    yield k + '.' + line
            else:
                yield '%s = %s' % (k, repr(v))

    def dump(self):
        return '\n'.join(self._flatten())

class RandomPool(object):
    _local = local()

    @classmethod
    def get(klass):
        if not hasattr(klass._local, 'pool'):
            klass._local = randpool.RandomPool()
        return klass._local

    @classmethod
    def hash_bytes(klass, value):
        from hashlib import sha256
        return sha256(value).digest()

    @classmethod
    def hash_string(klass, value):
        from hashlib import sha256
        return sha256(value).hexdigest()

    @classmethod
    def get_bytes(klass, num, event='aaa'):
        pool = klass.get()
        pool.stir()
        pool.add_event(klass.hash_bytes(event))
        pool.stir()
        result = pool.get_bytes(num)
        pool.stir()
        pool.add_event(klass.hash_bytes(event))
        pool.stir()
        return result

    @classmethod
    def get_string(klass, num, event='aaa'):
        from hashlib import sha256
        bytes = klass.get_bytes(num // 2)
        return klass.hash_string(bytes)
        
def gen_nonce():
    return RandomPool.get_bytes(20)
